﻿namespace DomainServices.Tools
{
    using Microsoft.Build.Evaluation;
    using Microsoft.Build.Exceptions;
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Text;

    internal class ProjectFileReader : IDisposable
    {
        private ILogger _logger;
        private ProjectCollection _projectCollection = new ProjectCollection();

        internal ProjectFileReader(ILogger logger)
        {
            if (logger == null)
            {
                throw new ArgumentNullException("logger");
            }
            this._logger = logger;
        }

        internal static string ConvertToFullPath(string path, string projectPath)
        {
            if (!Path.IsPathRooted(path))
            {
                path = Path.Combine(Path.GetDirectoryName(projectPath), path);
            }
            return Path.GetFullPath(path);
        }

        internal static string ConvertToRelativePath(string path, string projectPath)
        {
            string str = path;
            if (Path.IsPathRooted(path))
            {
                string fullPath = Path.GetFullPath(Path.GetDirectoryName(projectPath));
                str = Path.GetFullPath(path);
                if ((str.StartsWith(fullPath, StringComparison.OrdinalIgnoreCase) && (str.Length > fullPath.Length)) && (str[fullPath.Length] == Path.DirectorySeparatorChar))
                {
                    str = str.Substring(fullPath.Length + 1);
                }
            }
            return str;
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
            if (this._projectCollection != null)
            {
                this._projectCollection.Dispose();
                this._projectCollection = null;
            }
        }

        internal string GetPropertyValue(string projectPath, string propertyName)
        {
            string propertyValue = null;
            Project project = this.LoadProject(projectPath);
            if (project != null)
            {
                propertyValue = project.GetPropertyValue(propertyName);
            }
            return propertyValue;
        }

        internal Project LoadProject(string projectPath)
        {
            System.Func<Project, bool> func = null;
            if (string.IsNullOrEmpty(projectPath))
            {
                throw new ArgumentNullException("projectPath");
            }
            if (!File.Exists(projectPath))
            {
                this._logger.LogWarning(string.Format(CultureInfo.CurrentCulture, Resource.Project_Does_Not_Exist, new object[] { projectPath }));
                return null;
            }
            Project project = null;
            try
            {
                if (func == null)
                {
                    func = p => string.Equals(p.FullPath, projectPath, StringComparison.OrdinalIgnoreCase);
                }
                project = Enumerable.Where<Project>(this._projectCollection.LoadedProjects, func).FirstOrDefault<Project>();
                if (project == null)
                {
                    project = this._projectCollection.LoadProject(projectPath);
                }
            }
            catch (InvalidOperationException exception)
            {
                this._logger.LogWarning(string.Format(CultureInfo.CurrentCulture, Resource.Failed_To_Open_Project, new object[] { projectPath, exception.Message }));
            }
            catch (InvalidProjectFileException exception2)
            {
                this._logger.LogWarning(string.Format(CultureInfo.CurrentCulture, Resource.Failed_To_Open_Project, new object[] { projectPath, exception2.Message }));
            }
            return project;
        }

        internal IEnumerable<string> LoadProjectReferences(string projectPath)
        {
            IEnumerable<string> source = new string[0];
            Project project = this.LoadProject(projectPath);
            if (project != null)
            {
                this._logger.LogMessage(string.Format(CultureInfo.CurrentCulture, Resource.Analyzing_Project_References, new object[] { Path.GetFileName(projectPath) }));
                source = from i in project.GetItems("ProjectReference") select ConvertToFullPath(i.EvaluatedInclude, projectPath);
                if (!source.Any<string>())
                {
                    return source;
                }
                StringBuilder builder = new StringBuilder(string.Format(CultureInfo.CurrentCulture, Resource.Project_References_Found, new object[] { Path.GetFileName(projectPath) }));
                foreach (string str in source)
                {
                    builder.AppendLine();
                    builder.Append("    " + str);
                }
                this._logger.LogMessage(builder.ToString());
            }
            return source;
        }

        internal IEnumerable<string> LoadSourceFilesFromProject(string projectPath)
        {
            IEnumerable<string> enumerable = new string[0];
            Project project = this.LoadProject(projectPath);
            if (project == null)
            {
                return enumerable;
            }
            this._logger.LogMessage(string.Format(CultureInfo.CurrentCulture, Resource.Analyzing_Project_Files, new object[] { Path.GetFileName(projectPath) }));
            return (from i in project.GetItems("Compile") select ConvertToFullPath(i.EvaluatedInclude, projectPath));
        }
    }
}

